<template>
  <div class="face-recognition">
    <video ref="video" width="640" height="480" autoplay></video>
    <canvas ref="canvas" width="640" height="480"></canvas>
    <div>当前人流量：{{ peopleCount }}</div>
  </div>
</template>

<script>
import * as faceapi from "face-api.js";

export default {
  name: "FaceRecognition",
  data() {
    return {
      isLoaded: false,
      lastDetections: [], // 上一帧检测到的人脸
      peopleCount: 0, // 当前人流量计数
    };
  },
  mounted() {
    this.loadModels();
  },
  methods: {
    async loadModels() {
      try {
        await Promise.all([
          faceapi.nets.faceRecognitionNet.loadFromUri("/models"),
          faceapi.nets.faceLandmark68Net.loadFromUri("/models"),
          faceapi.nets.ssdMobilenetv1.loadFromUri("/models"),
        ]);
        this.isLoaded = true;
        this.startVideo();
      } catch (error) {
        console.error("Failed to load models:", error);
      }
    },
    startVideo() {
      if (navigator.mediaDevices && this.isLoaded) {
        navigator.mediaDevices
          .getUserMedia({ video: true })
          .then((stream) => {
            this.$refs.video.srcObject = stream;
            this.$refs.video.onloadedmetadata = () => {
              this.detectFaces();
            };
          })
          .catch((error) => console.error("getUserMedia error:", error));
      }
    },

    async detectFaces() {
      const video = this.$refs.video;
      const canvas = this.$refs.canvas;
      const ctx = canvas.getContext("2d");
      const detectionOptions = new faceapi.SsdMobilenetv1Options({
        minConfidence: 0.9,
      });

      let recentDetections = [];
      const detectionHistoryLength = 5;

      setInterval(async () => {
        if (video.readyState === video.HAVE_ENOUGH_DATA) {
          ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
          const detections = await faceapi
            .detectAllFaces(video, detectionOptions)
            .withFaceLandmarks();
          // console.log('查看获取帧',validDescriptors)
          // 确保只收集有效的面部描述符
          const validDescriptors = detections;
          console.log("查看获取帧", validDescriptors);
          recentDetections.push(
            ...validDescriptors.map((face) => face.descriptor)
          );

          // 限制历史长度并去重
          recentDetections = recentDetections.slice(-detectionHistoryLength);
          // console.log('查看获取帧',recentDetections)
          const uniqueDescriptors = Array.from(new Set(recentDetections));
          this.peopleCount = uniqueDescriptors.length; // 直接使用去重后的数组长度，因已排除undefined，无需JSON.stringify和parse

          faceapi.draw.drawDetections(canvas, detections);
          faceapi.draw.drawFaceLandmarks(canvas, detections);
        }
      }, 100);
    },
  },
  beforeDestroy() {
    // 清理视频流
    if (this.$refs.video.srcObject) {
      this.$refs.video.srcObject.getTracks().forEach((track) => track.stop());
    }
  },
};
</script>

<style scoped>
.face-recognition {
  position: relative;
}
</style>
